﻿using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Swift;

namespace Server
{
    /// <summary>
    /// 接受控制台输入
    /// </summary>
    public class ConsoleInput : Component, IFrameDrived
    {
        // 游戏服务器
        public GameServer Srv = null;

        Thread thr; // 等待输入的工作线程
        bool running = false;

        // 等待执行的指令
        ConcurrentQueue<Action> cmdQ = new ConcurrentQueue<Action>();

        public override void Init()
        {
            var up = GetCom<UserPort>();
            up.OnRequest("GMCmd", (Connection conn, IReadableBuffer data, IWriteableBuffer buff, Action end) =>
            {
                var strs = data.ReadString().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                var cmd = strs[0];
                var ps = strs.Length == 1 ? null : new string[strs.Length - 1];
                if (ps != null)
                    Array.Copy(strs, 1, ps, 0, ps.Length);

                if (!cmdHandlers.ContainsKey(cmd))
                {
                    buff.Write("unknown command: " + cmd);
                    end();
                }
                else
                {
                    PushCommand((r) =>
                    {
                        buff.Write(r);
                        end();
                    }, cmd, ps);
                }
            });

            OnCommand("stop", (ps) => { running = false; Srv.Stop(); return "stopped"; });
        }

        public void Start()
        {
            running = true;
            thr = new Thread(new ThreadStart(WorkingThread));
            thr.Start();
        }

        void WorkingThread()
        {
            var cmd = "";
            while (running)
            {
                cmd = Console.ReadLine();
                var ins = cmd.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                cmd = ins.Length > 0 ? ins[0] : "";
                var ps = ins.Length > 1 ? ins.SubArray(1, ins.Length - 1) : null;
                lock (cmdHandlers)
                {
                    if (!cmdHandlers.ContainsKey(cmd))
                        cmdQ.Enqueue(() => { Console.WriteLine("unknown command: " + cmd); });
                    else
                        cmdQ.Enqueue(() => { Console.WriteLine(cmdHandlers[cmd](ps)); });
                }
            }
        }

        public void PushCommand(Action<string> cb, string cmd, params string[] ps)
        {
            cmdQ.Enqueue(() => { cb(cmdHandlers[cmd](ps)); });
        }

        public void OnTimeElapsed(int te)
        {
            Action cmd = null;
            while (cmdQ.TryDequeue(out cmd))
                cmd();
        }

        Dictionary<string, Func<string[], string>> cmdHandlers = new Dictionary<string, Func<string[], string>>();
        public void OnCommand(string cmd, Func<string[], string> op)
        {
            lock(cmdHandlers)
                cmdHandlers[cmd] = op;
        }
    }
}

// 代理服务器后台输入
public class ConsoleInputAgent : Component
{
    Thread thr;
    bool running = false;
    Connection conn = null;
    public void Start(string srvAddr, int ciPort)
    {
        running = true;
        thr = new Thread(new ThreadStart(WorkingThread));
        thr.Start();

        var nc = GetCom<NetCore>();
        conn = nc.Connect2Peer(srvAddr, ciPort);
        Console.WriteLine("server connected.");
    }

    void WorkingThread()
    {
        while (running)
        {
            var str = Console.ReadLine();
            var buff = conn.BeginRequest("UserPort", (data) =>
            {
                var r = data.ReadString();
                Console.WriteLine(r);
            });

            buff.Write("GMCmd");
            buff.Write(str);
            conn.End(buff);
        }
    }
}
